<template>
  <div ref="box" class="box"></div>
</template>
<script setup>
import * as THREE from 'three'
import * as d3 from 'd3'

import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
import { ref, onMounted, onUnmounted, inject } from "vue";
import Base from '@/utils/Base'
async function loadMap() {
  const fileLoader = new THREE.FileLoader()
  let res = await Promise.all([fileLoader.loadAsync('/data/china.json'), fileLoader.loadAsync('/data/chinaedg.json')])
  console.log(res instanceof Array);
  if (res instanceof Array) {

    // 创建地图
    createMap(res[0])
  }
}
const projection = d3
  .geoMercator() //地图投影方式
  .center([108.5525, 34, 3227]) //地图中心点
  .scale(84) //缩放
  .translate([0, 0]) //移动
let chinaObj = new THREE.Object3D()
function createMap(res) {
  res = JSON.parse(res)
  // 省份 province
  res.features.forEach(province => {
    // Polygon
    let provinceObj = new THREE.Object3D()

    if (province.geometry.type == 'MultiPolygon') {
      province.geometry.coordinates.forEach(multiPolygon => {
        multiPolygon.forEach(polygon => {
          const shape = new THREE.Shape();
          let arr = []
          polygon.forEach((coord, index) => {
            let [x, y] = projection(coord)
            if (index == 0) {
              shape.moveTo(x, -y)
            } else {
              shape.lineTo(x, -y)
            }
            arr.push(x, -y, 10)

          })
          let mesh = createPolygon(shape, arr, province)
          provinceObj.add(mesh)
        })
      })

    } 
    else if (province.geometry.type == 'Polygon') {

      province.geometry.coordinates.forEach(polygon => {
        const shape = new THREE.Shape();
        let arr = []
        polygon.forEach((coord, index) => {
          let [x, y] = projection(coord)
          if (index == 0) {
            shape.moveTo(x, -y)
          } else {
            shape.lineTo(x, -y)
          }
          arr.push(x, -y, 10)
        })
        let mesh = createPolygon(shape, arr, province)
        provinceObj.add(mesh)
      })

    }
    chinaObj.add(provinceObj)
  })

  base.scene.add(chinaObj)

}
const extrudeMats = [
  new THREE.MeshStandardMaterial({
    color: 0x0000ff,
    transparent: true,
    opacity: 0.85,
    blending: THREE.AdditiveBlending,
  }),
  new THREE.MeshStandardMaterial({
    color: 0x0000ff,
    transparent: true,
    opacity: 0.35,
    blending: THREE.AdditiveBlending,
  }),
]

const edgMat = new THREE.LineBasicMaterial({
  color: 0xfffffff,
  blending: THREE.AdditiveBlending,

})
function createPolygon(shape, arr, province) {
  const extrudeSettings = {
	steps: 2,
	depth: 10,
	// bevelEnabled: true,
	// bevelThickness: 1,
	// bevelSize: 1,
	// bevelOffset: 0,
	// bevelSegments: 1
}

  let geo = new THREE.ExtrudeGeometry(shape,extrudeSettings)
  let mesh = new THREE.Mesh(geo, extrudeMats)
  if (province.properties.name) {
    mesh.name = province.properties.name
  }
  // 画线
  let buffer = new THREE.BufferGeometry()
  buffer.setAttribute(
    'position',
    new THREE.BufferAttribute(new Float32Array(arr), 3))
  let line = new THREE.Line(buffer, edgMat)
  chinaObj.add(line)
  return mesh
}
function update() {
  requestAnimationFrame(update)
  base.update()

  controls.update()
}
function resize() {
  base.resize()

}
let base, controls
const box = ref(null)
onMounted(async () => {

  base = new Base(box.value)
  base.camera.position.z = 60
  await loadMap()
  base.camera.updateProjectionMatrix()
  base.addAmbientLight(0.55)
  // await loadMap()
  controls = new OrbitControls(base.camera, base.renderer.domElement)
  // createBox()

  update()
  window.addEventListener('resize', resize)
});
function createBox() {
  const geometry = new THREE.BoxGeometry(2000, 2000, 2000,);
  const material = new THREE.MeshBasicMaterial({ color: 0x00ff00 });
  const cube = new THREE.Mesh(geometry, material);

  base.scene.add(cube);
}
</script>
<style scoped lang="scss">
.box {
  width: 800px;
  height: 500px;
  width: 100%;
  height: 100%;
  border: 10px solid red;
  box-sizing: border-box;
}
</style>
